package server.skill

import client.MapleCharacter
import client.inventory.MapleInventoryType
import constants.skills.*
import handling.opcode.SendPacketOpcode
import provider.MapleDataTool
import server.MapleStatEffect
import server.MapleStatEffectFactory
import server.img.MapleWZImg
import server.life.MapleMonster
import tools.DateUtil
import tools.Randomizer
import tools.data.output.MaplePacketLittleEndianWriter
import java.awt.Point
import java.awt.Rectangle


/**
 * 免责声明：本模拟器源代码下载自ragezone.com，仅用于技术研究学习，无任何商业行为。
 */
object MapleForceAtomFactory {

    private val forceAtoms: HashMap<Int, Map<Int, ForceAtomDataEntry>> = HashMap()

    fun initialize() {
        forceAtoms.clear()
        val characterEff = MapleWZImg.effect.getData("CharacterEff.img")
        val forceAtomIt = characterEff.getChildByPath("forceAtom").iterator()
        while (forceAtomIt.hasNext()) {
            val forceAtom = forceAtomIt.next()
            val name = forceAtom.name.toInt()
            var firstImpactMin = 45
            var firstImpactMax = 50
            var secondImpactMin = 30
            var secondImpactMax = 35
            val infoData = forceAtom.getChildByPath("info")
            if (infoData != null) {
                firstImpactMin = MapleDataTool.getInt(infoData.getChildByPath("firstImpactMin"), 45)
                firstImpactMax = MapleDataTool.getInt(infoData.getChildByPath("firstImpactMax"), 50)
                secondImpactMin = MapleDataTool.getInt(infoData.getChildByPath("secondImpactMin"), 30)
                secondImpactMax = MapleDataTool.getInt(infoData.getChildByPath("secondImpactMax"), 35)
            }
            val atomData = forceAtom.getChildByPath("atom")
            if (atomData != null) {
                val infos = HashMap<Int, ForceAtomDataEntry>()
                val atomIt = atomData.iterator()
                while (atomIt.hasNext()) {
                    val info = atomIt.next()
                    if (info.name.length <= 2) {
                        val atomName = info.name.toInt()
                        var startPoints = ArrayList<Point>()
                        val startInfoData = info.getChildByPath("startInfo")
                        if (startInfoData != null) {
                            MapleDataTool.getInt(startInfoData.getChildByPath("startYmin"), 0)
                            MapleDataTool.getInt(startInfoData.getChildByPath("startYmax"), 0)
                            MapleDataTool.getInt(startInfoData.getChildByPath("arriveTime"), 0)
                            MapleDataTool.getInt(startInfoData.getChildByPath("updownYmin"), 0)
                            MapleDataTool.getInt(startInfoData.getChildByPath("updownYmax"), 0)
                            MapleDataTool.getInt(startInfoData.getChildByPath("updownTimeMin"), 0)
                            MapleDataTool.getInt(startInfoData.getChildByPath("updownTimeMax"), 0)
                        }
                        MapleDataTool.getInt(info.getChildByPath("isHoming"), 0)
                        MapleDataTool.getInt(info.getChildByPath("holdRotate"), 0)
                        val startPointData = info.getChildByPath("startPoint")
                        if (startPointData != null) {
                            startPoints = ArrayList()
                            val startPointIt = startPointData.iterator()
                            while (startPointIt.hasNext()) {
                                val nextPointData = startPointIt.next()
                                var i = 0
                                while (nextPointData.getChildByPath(i.toString()) != null) {
                                    val point = MapleDataTool.getPoint(nextPointData.getChildByPath(i.toString()))
                                    if (point != null) {
                                        startPoints.add(point)
                                    }
                                    ++i
                                }
                            }
                        }
                        val forceAtomEntry = ForceAtomDataEntry()
                        forceAtomEntry.startPoint = startPoints
                        forceAtomEntry.firstImpactMin = firstImpactMin
                        forceAtomEntry.firstImpactMax = firstImpactMax
                        forceAtomEntry.secondImpactMin = secondImpactMin
                        forceAtomEntry.secondImpactMax = secondImpactMax
                        infos[atomName] = forceAtomEntry
                    }
                }
                forceAtoms[name] = infos
            }
        }
    }

    fun createForceAtom(player: MapleCharacter, effect: MapleStatEffect, toMobOIDs: List<Int>): MapleForceAtom =
            createForceAtom(player, effect, 0, toMobOIDs, player.position)

    fun createForceAtom(player: MapleCharacter, effect: MapleStatEffect, forceOID: Int): MapleForceAtom =
            createForceAtom(player, effect, forceOID, emptyList(), player.position)

    fun createForceAtom(player: MapleCharacter, effect: MapleStatEffect, forceOID: Int, y: Int): MapleForceAtom =
            createForceAtom(player, effect, forceOID, y, 0, emptyList(), player.position)

    fun createForceAtom(player: MapleCharacter, effect: MapleStatEffect, forceOID: Int, toMobOIDs: List<Int>, point: Point): MapleForceAtom =
            createForceAtom(player, effect, 1, forceOID, 0, toMobOIDs, point)

    private fun createForceAtom(player: MapleCharacter, effect: MapleStatEffect, forceOID: Int, fromMobOID: Int, toMobOID: Int, list: List<Int>, point: Point): MapleForceAtom {
        val forceAtom = MapleForceAtom()
        forceAtom.isFrom = fromMobOID > 0
        forceAtom.ownerID = player.id
        forceAtom.point = point
        forceAtom.toMobOIDs = list
        when (effect.sourceid) {
            火毒.审判之焰 -> {
                forceAtom.fromMobOID = 0
                forceAtom.type = 3
                forceAtom.toMobOID = 0
                forceAtom.skillID = 火毒.审判之焰_人偶
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 2, 20, 50, 500, point)
            }
            神射手.三彩箭矢_魔法, 神射手.三彩箭矢, 神射手.进阶箭筒 -> {
                forceAtom.fromMobOID = 0
                forceAtom.type = 10
                forceAtom.toMobOID = toMobOID
                forceAtom.skillID = if (effect.sourceid == 神射手.进阶箭筒) 神射手.进阶箭筒_魔法 else 神射手.三彩箭矢_魔法
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 0, 20, 50, 53, point)
            }
            4100011, 隐士.刺客标记 -> {
                forceAtom.fromMobOID = fromMobOID
                forceAtom.type = 11
                forceAtom.toMobOID = 0
                forceAtom.skillID = 隐士.刺客标记_飞镖
                forceAtom.rectangle = MapleStatEffectFactory.calculateBoundingBox(point, true, Point(-120, -100), Point(100, 100), 0)
                forceAtom.cosumeItemID = player.getInventory(MapleInventoryType.USE).getDartsSlot(player.level.toInt())?.itemId ?: 0
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, 40, 100, 200, point)
            }
            隐士.隐士标记 -> {
                forceAtom.fromMobOID = fromMobOID
                forceAtom.type = 11
                forceAtom.toMobOID = 0
                forceAtom.skillID = 隐士.隐士标记_飞镖
                forceAtom.rectangle = MapleStatEffectFactory.calculateBoundingBox(point, true, Point(-120, -100), Point(100, 100), 0)
                forceAtom.cosumeItemID = player.getInventory(MapleInventoryType.USE).getDartsSlot(player.level.toInt())?.itemId ?: 0
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 2, 40, 100, 200, point)
            }
            炎术士.轨道烈焰 -> {
                forceAtom.skillID = 炎术士.轨道烈焰_LINK
                forceAtom.type = 17
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, 40, 100, 30, point)
            }
            炎术士.轨道烈焰II -> {
                forceAtom.skillID = 炎术士.轨道烈焰II_LINK
                forceAtom.type = 17
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 2, 40, 100, 30, point)
            }
            炎术士.轨道烈焰III -> {
                forceAtom.skillID = 炎术士.轨道烈焰III_LINK
                forceAtom.type = 17
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 3, 40, 100, 30, point)
            }
            炎术士.轨道烈焰IV -> {
                forceAtom.skillID = 炎术士.轨道烈焰IV_LINK
                forceAtom.type = 17
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 4, 25, 100, 30, point)
            }
//            风灵使者.狂风肆虐I, 风灵使者.狂风肆虐II, 风灵使者.狂风肆虐III -> {
//                forceAtom.type = 7
//                forceAtom.skillID = effect.sourceid
//                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 2, 42, if (Randomizer.isSuccess(50)) 50 else 180, 40, point)
//            }
//            风灵使者.狂风肆虐I_攻击, 风灵使者.狂风肆虐II_攻击, 风灵使者.狂风肆虐III_攻击 -> {
//                forceAtom.type = 7
//                forceAtom.skillID = effect.sourceid
//                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, 42, if (Randomizer.isSuccess(50)) 50 else 180, 40, point)
//            }
            风灵使者.暴风灭世 -> {
                forceAtom.type = 8
                forceAtom.toMobOID = toMobOID
                forceAtom.skillID = effect.sourceid
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, 15, if (player.isFacingLeft) 90 else 280, 60, point)
            }
            夜行者.影子蝙蝠_召唤兽, 夜行者.影子蝙蝠_攻击 -> {
                forceAtom.type = if (forceAtom.isFrom) 16 else 15
                forceAtom.skillID = 夜行者.影子蝙蝠_攻击
                forceAtom.fromMobOID = fromMobOID
                forceAtom.toMobOID = toMobOID
                forceAtom.rectangle = MapleStatEffectFactory.calculateBoundingBox(point, true, Point(-120, -100), Point(100, 100), 0)
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, if (forceAtom.isFrom) 1 else 2, 32, 280, if (forceAtom.isFrom) 30 else 300, point)
            }
            幻影.王牌, 幻影.小丑_1 -> {
                forceAtom.type = 1
                forceAtom.toMobOID = toMobOID
                forceAtom.skillID = 幻影.小丑_1
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 2, 35, 7, 60, point)
            }
            幻影.卡片雪舞, 幻影.黑色秘卡 -> {
                forceAtom.type = 1
                forceAtom.toMobOID = toMobOID
                forceAtom.skillID = effect.sourceid
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, if (effect.sourceid == 幻影.黑色秘卡) 2 else 1, 25, 7, 60, point)
            }
            幻影.卡牌审判, 幻影.卡牌审判_高级 -> {
                forceAtom.type = 1
                forceAtom.toMobOID = toMobOID
                forceAtom.skillID = if (effect.sourceid == 幻影.卡牌审判_高级) 幻影.黑色秘卡 else 幻影.卡片雪舞
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, if (effect.sourceid == 幻影.卡牌审判_高级) 2 else 1, 25, 7, 60, point)
            }
            隐月.狐灵_1, 隐月.火狐灵_1 -> {
                forceAtom.fromMobOID = fromMobOID
                forceAtom.type = if (forceAtom.isFrom) 4 else 13
                forceAtom.toMobOID = toMobOID
                forceAtom.skillID = effect.sourceid
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, if (effect.sourceid == 隐月.狐灵_1) if (forceAtom.isFrom) 4 else 1 else if (forceAtom.isFrom) 5 else 2, 25, if (player.isFacingLeft) 90 else 280, 60, point)
            }
            恶魔猎手.恶魔血月斩, 恶魔猎手.恶魔血月斩1, 恶魔猎手.恶魔血月斩2, 恶魔猎手.恶魔血月斩3, 恶魔猎手.地狱夺魂, 恶魔猎手.恶魔觉醒_1, 恶魔猎手.恶魔觉醒_2, 恶魔猎手.恶魔觉醒_3, 恶魔猎手.恶魔觉醒_4 -> {
                val color = Randomizer.nextInt(if (player.getSkillLevel(恶魔猎手.极限精气吸收) > 0) 10 else 6)
                forceAtom.fromMobOID = fromMobOID
                forceAtom.type = 0
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, color, 30, 65, 0, point)
            }
            恶魔复仇者.追击盾, 恶魔复仇者.追击盾_攻击 -> {
                forceAtom.fromMobOID = fromMobOID
                forceAtom.type = if (forceAtom.isFrom) 4 else 3
                forceAtom.toMobOID = toMobOID
                forceAtom.skillID = 恶魔复仇者.追击盾_攻击
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 3, if (forceAtom.isFrom) 80 else 20, if (player.isFacingLeft) Randomizer.rand(30, 90) else Randomizer.rand(200, 280), if (forceAtom.isFrom) 60 else 500, point)
            }
            机械师.辅助导弹, 机械师.导航辅助导弹 -> {
                forceAtom.type = 20
                forceAtom.skillID = effect.sourceid
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, if (effect.sourceid == 35101002) 0 else 2, 37, if (player.isFacingLeft) 90 else 280, 512, point)
            }
            尖兵.宙斯盾系统 -> {
                forceAtom.type = 5
                forceAtom.skillID = 尖兵.宙斯盾系统_攻击
                forceAtom.fromMobOID = fromMobOID
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 0, 32, 96, 256, point)
            }
            尖兵.精准火箭 -> {
                forceAtom.type = 6
                forceAtom.skillID = effect.sourceid
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 0, 20, 34, 0, point)
            }
//            狂龙战士.剑刃之壁, 狂龙战士.进阶剑刃之壁, 狂龙战士.剑刃之壁击打 -> {
//                forceAtom.type = 2
//                forceAtom.skillID = effect.sourceid
//                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 2, 16, if (player.isFacingLeft) 90 else 280, 16, point)
//            }
//            狂龙战士.剑刃之壁_变身, 狂龙战士.进阶剑刃之壁_变身, 狂龙战士.剑刃之壁击打_1 -> {
//                forceAtom.type = 2
//                forceAtom.skillID = effect.sourceid
//                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 3, 16, if (player.isFacingLeft) 90 else 280, 16, point)
//            }
            爆莉萌天使.灵魂吸取_攻击, 爆莉萌天使.灵魂吸取, 爆莉萌天使.灵魂吸取专家 -> {
                forceAtom.fromMobOID = fromMobOID
                forceAtom.type = if (forceAtom.isFrom) 4 else 3
                forceAtom.toMobOID = toMobOID
                forceAtom.skillID = 爆莉萌天使.灵魂吸取_攻击
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, if (forceAtom.isFrom) 32 else 16, if (player.isFacingLeft) 90 else 280, if (forceAtom.isFrom) 32 else 300, point)
            }
            超能力者.心灵传动 -> {
                forceAtom.type = 22
                forceAtom.toMobOID = toMobOID
                forceAtom.skillID = effect.sourceid
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 0, 18, if (player.isFacingLeft) 90 else 280, 300, point)
            }
            火毒.制裁火球 -> {
                forceAtom.type = 28
                forceAtom.toMobOID = toMobOID
                forceAtom.skillID = effect.sourceid
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, 36, if (player.isFacingLeft) 30 else 50, 528, point)
            }
            奇袭者.心雷合一, 奇袭者.心雷合一_1 -> {
                forceAtom.fromMobOID = fromMobOID
                forceAtom.type = 27
                forceAtom.toMobOID = toMobOID
                forceAtom.skillID = 奇袭者.心雷合一_1
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, if (forceAtom.isFrom) 4 else 1, 25, if (player.isFacingLeft) 10 else 15, 0, point)
            }
//            神射手.残影之矢 -> {
//                forceAtom.fromMobOID = 0
//                forceAtom.type = 31
//                forceAtom.toMobOID = toMobOID
//                forceAtom.skillID = effect.sourceid
//                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, 20, 70, 53, point)
//            }
//            幻影.黑杰克, 幻影.黑杰克_1 -> {
//                forceAtom.fromMobOID = fromMobOID
//                forceAtom.type = 33
//                forceAtom.toMobOID = toMobOID
//                forceAtom.skillID = 幻影.黑杰克_1
//                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 32, 70, 70, if (fromMobOID == 0) 760 else 0, point)
//            }
//            风灵使者.懒虫 -> {
//                forceAtom.type = 34
//                forceAtom.toMobOID = toMobOID
//                forceAtom.skillID = effect.sourceid
//                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, 36, if (player.isFacingLeft) 30 else 50, 528, point)
//            }
//            机械师.微型导弹箱 -> {
//                forceAtom.type = 30
//                forceAtom.skillID = effect.sourceid
//                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, 48, 37, 1440, point)
//            }
            弓箭手.向导之箭 -> {
                forceAtom.type = 27
                forceAtom.skillID = effect.sourceid
                forceAtom.rectangle = MapleStatEffectFactory.calculateBoundingBox(point, true, Point(-120, -100), Point(100, 100), 0)
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, 48, 90, 840, point)
            }
//            圣晶使徒.秘技_标枪, 152120001 -> {
//                forceAtom.type = 36
//                forceAtom.skillID = effect.sourceid
//                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 2, 2, 50, 390, point)
//            }
//            圣晶使徒.荣耀之翼_标枪进化2 -> {
//                forceAtom.type = 41
//                forceAtom.skillID = effect.sourceid
//                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, 48, 8, 310, point)
//            }
            152120002 -> {
                forceAtom.type = 39
                forceAtom.skillID = effect.sourceid
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, 64, 24, 310, point)
            }
//            圣晶使徒.荣耀之翼_标枪进化 -> {
//                forceAtom.type = 37
//                forceAtom.skillID = effect.sourceid
//                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 1, 2, 50, 390, point)
//            }
            80011585, 80011586, 80011587, 80011588, 80011589, 80011590, 80011635 -> {
                forceAtom.type = 17
                forceAtom.skillID = effect.sourceid
                forceAtom.forceAtomEntry = createForceList(player, effect, forceOID, forceAtom.type, 2, 16, if (player.isFacingLeft) 90 else 280, 16, point)
            }
            400021044, 400021045 -> {
                forceAtom.fromMobOID = fromMobOID
                forceAtom.type = 3
                forceAtom.toMobOID = toMobOID
                forceAtom.skillID = 400021045
                createForceList(player, effect, forceOID, forceAtom.type, 6, 10, 70, 90, point)
            }
        }
        return forceAtom
    }

    private fun createForceList(player: MapleCharacter, effect: MapleStatEffect, forceOID: Int, type: Int, color: Int, u: Int, v: Int, w: Int, point: Point): List<ForceAtomEntry> {
        val ret = ArrayList<ForceAtomEntry>()
        val forceAtomData = forceAtoms[type]
        if (forceAtomData != null) {
            val entry = forceAtomData[Math.min(forceAtomData.size, color + 1)]
            if (entry != null) {
                for (i in 1..effect.getBulletCount(player)) {
                    val forceAtomEntry = ForceAtomEntry()
                    forceAtomEntry.oid = player.map.spawnedForcesOnMap * 100 + forceOID
                    forceAtomEntry.color = color
                    forceAtomEntry.firstImpactMin = Randomizer.rand(u - 6, u)
                    forceAtomEntry.firstImpactMax = Randomizer.rand(entry.secondImpactMin, entry.secondImpactMax)
                    forceAtomEntry.secondImpactMin = Randomizer.rand(v - 20, v)
                    forceAtomEntry.secondImpactMax = w
                    var point2 = Point()
                    if (effect.sourceid == 152001001 || effect.sourceid == 152120001 || effect.sourceid == 152110004) {
                        forceAtomEntry.firstImpactMin = 50
                        forceAtomEntry.firstImpactMax = 50
                        forceAtomEntry.secondImpactMin = 0
                        point2 = Point(-48, 7)
                    }
                    if (effect.sourceid == 152120002) {
                        point2 = point
                    }
                    if (effect.sourceid == 400051017 || effect.sourceid == 400021001 || effect.sourceid == 400031022) {
                        point2.x = Randomizer.rand(-600 + player.position.x, 600 + player.position.x)
                        point2.y = Randomizer.rand(-300 + player.position.y, 50 + player.position.y)
                    }
                    if (effect.sourceid == 400031000) {
                        forceAtomEntry.firstImpactMin = 43
                        forceAtomEntry.firstImpactMax = 3
                        forceAtomEntry.secondImpactMin = 90
                    }
                    forceAtomEntry.point = point2
                    forceAtomEntry.creatTime = System.currentTimeMillis()
                    forceAtomEntry.mobCount = effect.mobCount
                    forceAtomEntry.y = 0
                    ret.add(forceAtomEntry)
                }
            }
        }
        return ret
    }

    fun createForceList(player: MapleCharacter, list: List<MapleMonster>, x: Int): List<ForceAtomEntry> {
        val ret = ArrayList<ForceAtomEntry>()
        val forceAtomData = forceAtoms[12]
        if (forceAtomData != null) {
            val entry = forceAtomData[Math.min(forceAtomData.size, 2)]
            if (entry != null) {
                list.forEach { mob ->
                    run {
                        val forceAtomEntry = ForceAtomEntry()
                        forceAtomEntry.oid = player.map.spawnedForcesOnMap
                        forceAtomEntry.color = 1
                        forceAtomEntry.firstImpactMin = Randomizer.rand(entry.firstImpactMin, entry.firstImpactMax)
                        forceAtomEntry.firstImpactMax = Randomizer.rand(entry.secondImpactMin, entry.secondImpactMax)
                        forceAtomEntry.secondImpactMin = Randomizer.rand(20, 45)
                        forceAtomEntry.secondImpactMax = 1000
                        forceAtomEntry.point = Point(mob.position.x - player.position.x, mob.position.y - player.position.y)
                        forceAtomEntry.creatTime = System.currentTimeMillis()
                        forceAtomEntry.mobCount = 0
                        forceAtomEntry.y = 0
                        ret.add(forceAtomEntry)
                    }
                }
            }
        }
        return ret
    }

    fun createForceList(player: MapleCharacter, effect: MapleStatEffect, list: List<Int>, points: List<Point>): MapleForceAtom {
        val t = MapleForceAtom()
        t.ownerID = player.id
        t.type = if (effect.sourceid == 155111207) 48 else 23
        t.toMobOID = 0
        t.toMobOIDs = list
        t.skillID = effect.sourceid
        val list3 = java.util.ArrayList<ForceAtomEntry>()
        val map = forceAtoms[if (effect.sourceid == 155111207) 48 else 23]
        val k = map?.get(Math.min(map.size, (if (effect.sourceid == 22170070) 2 else if (effect.sourceid == 155111207) 0 else 1) + 1))
        if (map != null && k != null) {
            points.forEach {
                val forceAtomEntry = ForceAtomEntry()
                forceAtomEntry.oid = player.map.spawnedForcesOnMap
                forceAtomEntry.color = if (effect.sourceid == 22170070) 2 else if (effect.sourceid == 155111207) 0 else 1
                forceAtomEntry.firstImpactMin = Randomizer.rand(k.firstImpactMin, k.firstImpactMax)
                forceAtomEntry.firstImpactMax = Randomizer.rand(k.secondImpactMin, k.secondImpactMax)
                forceAtomEntry.secondImpactMin = Randomizer.rand(64, 79)
                forceAtomEntry.secondImpactMax = 512
                forceAtomEntry.point = it
                forceAtomEntry.creatTime = System.currentTimeMillis()
                forceAtomEntry.mobCount = 1
                forceAtomEntry.y = 0
                list3.add(forceAtomEntry)
            }
            for (point in points) {
            }
        }
        t.forceAtomEntry = list3
        return t
    }

    fun createForceList(player: MapleCharacter, effect: MapleStatEffect, points: List<Point>, x: Int): List<ForceAtomEntry> {
        val ret = ArrayList<ForceAtomEntry>()
        val forceAtomData = forceAtoms[23]
        if (forceAtomData != null) {
            val entry = forceAtomData[Math.min(forceAtomData.size, (if (effect.sourceid == 22170070) 2 else 1) + 1)]
            if (entry != null) {
                points.forEach {
                    val forceAtomEntry = ForceAtomEntry()
                    forceAtomEntry.oid = player.map.spawnedForcesOnMap
                    forceAtomEntry.color = if (effect.sourceid == 22170070) 2 else 1
                    forceAtomEntry.firstImpactMin = Randomizer.rand(entry.firstImpactMin, entry.firstImpactMax)
                    forceAtomEntry.firstImpactMax = Randomizer.rand(entry.secondImpactMin, entry.secondImpactMax)
                    forceAtomEntry.secondImpactMin = Randomizer.rand(64, 79)
                    forceAtomEntry.secondImpactMax = 512
                    forceAtomEntry.point = it
                    forceAtomEntry.creatTime = System.currentTimeMillis()
                    forceAtomEntry.mobCount = 1
                    forceAtomEntry.y = 0
                    ret.add(forceAtomEntry)
                }
            }
        }
        return ret
    }
}

data class ForceAtomDataEntry(var startPoint: ArrayList<Point> = ArrayList(), var firstImpactMin: Int = 0, var firstImpactMax: Int = 0, var secondImpactMin: Int = 0, var secondImpactMax: Int = 0)

data class MapleForceAtom(
        var isFrom: Boolean = false,
        var ownerID: Int = 0,
        var fromMobOID: Int = 0,
        var type: Int = 0,
        var skillID: Int = 0,
        var toMobOID: Int = 0,
        var toMobOIDs: List<Int> = ArrayList(),
        var rectangle: Rectangle = Rectangle(),
        var cosumeItemID: Int = 0,
        var point: Point = Point(),
        var forceAtomEntry: List<ForceAtomEntry> = ArrayList(),
        var flameDirection: Int = 0
) {
    fun getPacket(): ByteArray {
        val mplew = MaplePacketLittleEndianWriter()

        mplew.writeShort(SendPacketOpcode.GAIN_FORCE.value)
        mplew.writeBool(isFrom)
        mplew.writeInt(ownerID)
        if (isFrom) {
            mplew.writeInt(fromMobOID)
        }
        mplew.writeInt(type)
        if (type > 0 && type != 9 && type != 14 && type != 29 && type != 35 && type != 42) {
            if (type != 36 && type != 37) {
                mplew.write(1)
                when (type) {
                    2, 3, 6, 7, 11, 12, 13, 17, 19, 20, 21, 23, 24, 25, 27, 28, 30, 32, 34, 38, 39, 40, 41, 47, 48 -> {
                        mplew.writeInt(toMobOIDs.size)
                        toMobOIDs.forEach(mplew::writeInt)
                    }
                    else -> {
                        mplew.writeInt(toMobOID)
                    }
                }
            }
            mplew.writeInt(skillID)
        }
        forceAtomEntry.forEach {
            mplew.write(1)
            mplew.writeInt(it.oid)
            mplew.writeInt(it.color)
            mplew.writeInt(it.firstImpactMin)
            mplew.writeInt(it.firstImpactMax)
            mplew.writeInt(it.secondImpactMin)
            mplew.writeInt(it.secondImpactMax)
            mplew.writePosAsInt(it.point)
            mplew.writeInt(DateUtil.getTime(it.creatTime))
            mplew.writeInt(it.mobCount)
            mplew.writeInt(it.y)
            mplew.writeInt(0)
            if (skillID >= 80011585 && (skillID <= 80011591 || skillID == 80011635)) {
                mplew.writeInt(it.point.x)
                mplew.writeInt(it.point.y)
            }
        }
        mplew.write(0)
        when (type) {
            11 -> {
                mplew.writeRect(rectangle)
                mplew.writeInt(cosumeItemID)
            }
            9, 15 -> {
                mplew.writeRect(rectangle)
            }
            17 -> {
                mplew.writeInt(flameDirection)
                mplew.writeInt(500)
            }
            4, 16, 18, 26, 33 -> {
                mplew.writePosAsInt(point)
            }
            27 -> {
                mplew.writeInt(-500)
                mplew.writeInt(-350)
                mplew.writeInt(500)
                mplew.writeInt(350)
                mplew.writeInt(0)
            }
            28, 34 -> {
                mplew.writeRect(rectangle)
                mplew.writeInt(0)
            }
            36 -> {
                mplew.writeInt(5)
                mplew.writeInt(550)
                mplew.writeInt(0)
                mplew.writeInt(-300)
                mplew.writeInt(-300)
                mplew.writeInt(300)
                mplew.writeInt(300)
                mplew.writeInt(-50)
                mplew.writeInt(-50)
                mplew.writeInt(50)
                mplew.writeInt(50)
                mplew.writeInt(0)
            }
            39 -> {
                mplew.writeInt(0)
                mplew.writeInt(0)
                mplew.writeInt(0)
                mplew.writeInt(-100)
                mplew.writeInt(-100)
                mplew.writeInt(100)
                mplew.writeInt(100)
            }
            37 -> {
                mplew.writeInt(0)
                mplew.writeInt(-300)
                mplew.writeInt(-300)
                mplew.writeInt(300)
                mplew.writeInt(300)
                mplew.writeInt(200)
                mplew.writeInt(0)
            }
            35 -> {
                mplew.writeInt(0)
                mplew.writeInt(0)
            }
            29 -> {
                mplew.writeInt(0)
                mplew.writeInt(0)
                mplew.writeInt(0)
                mplew.writeInt(0)
            }
            42 -> {
                mplew.writeInt(0)
                mplew.writeInt(0)
            }
        }
        return mplew.packet

    }
}

data class ForceAtomEntry(
        var oid: Int = 0,
        var color: Int = 0,
        var firstImpactMin: Int = 0,
        var firstImpactMax: Int = 0,
        var secondImpactMin: Int = 0,
        var secondImpactMax: Int = 0,
        var point: Point = Point(),
        var creatTime: Long = 0,
        var mobCount: Int = 0,
        var y: Int = 0,
        var subPoint: Point = Point()
)